<!DOCTYPE html>
<html lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>MIPS ABI Changes in GCC 3.4</title>
<link rel="stylesheet" type="text/css" href="https://gcc.gnu.org/gcc.css" />
</head>

<body>

<h1>MIPS ABI Changes in GCC 3.4</h1>

<p>GCC 3.4 fixes several cases in which earlier releases would not
   follow the MIPS calling conventions.  This document describes
   each fix and the kind of code it will affect.  In each case,
   GCC 3.4 will not be binary compatible with earlier releases.</p>

<p>Most of the fixes are related to the handling of structure
   and union types.  In the summary below, "aggregate" refers
   to both structures and unions.</p>

<p>Note that IRIX 6 configurations used to work around
   <a href="#B">B</a> and <a href="#E">E</a> by providing wrappers
   for certain libc functions.  These wrappers are not needed for 3.4
   and have been removed.  It should be possible to link code generated
   by GCC 3.4 directly with code generated by SGI's compilers.</p>

<h2>A. Small aggregate arguments (1)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>o32</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>little</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>An aggregate argument is passed in a register; and</li>
	  <li>that argument is smaller than 4 bytes.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The register was padded at the least significant end.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The register is padded at the most significant end.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { char c[2]; };
void f (struct s x);</pre>

	<p><code>x</code> is passed in argument register <code>$4</code>,
	   which is laid out as follows:</p>

	<table class="padding5">
	  <tr class="center">
	  <th></th> <th>7-0</th> <th>15-8</th> <th>23-16</th> <th>31-24</th>
	  </tr>

	  <tr class="center">
	  <th class="left">Old&nbsp;behavior</th>
	  <td>padding</td> <td>padding</td> <td>c[0]</td> <td>c[1]</td>
	  </tr>

	  <tr class="center">
	  <th class="left">New&nbsp;behavior</th>
	  <td>c[0]</td> <td>c[1]</td> <td>padding</td> <td>padding</td>
	  </tr>
	</table></td>
  </tr>
</table>

<h2 id="B">B. Small aggregate arguments (2)</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>n32 and n64</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>big</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>An aggregate argument is passed in a register; and</li>
	  <li>that argument is smaller than 8 bytes.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The register was padded at the most significant end.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The register is padded at the least significant end.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { char c[2]; };
void f (struct s x);</pre>

	<p><code>x</code> is passed in argument register
	   <code>$4</code>, which is laid out as follows:</p>

	<table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>63-56</th> <th>55-48</th> <th>47-40</th> <th>39-32</th>
	  <th>31-24</th> <th>23-16</th> <th>15-8</th> <th>7-0</th>
	  </tr>

	  <tr class="center">
	  <th class="left">Old&nbsp;behavior</th>
	  <td>padding</td> <td>padding</td> <td>padding</td> <td>padding</td>
	  <td>padding</td> <td>padding</td> <td>c[0]</td> <td>c[1]</td>
	  </tr>

	  <tr class="center">
	  <th class="left">New&nbsp;behavior</th>
	  <td>c[0]</td> <td>c[1]</td> <td>padding</td> <td>padding</td>
	  <td>padding</td> <td>padding</td> <td>padding</td> <td>padding</td>
	  </tr>
	</table></td>
  </tr>
</table>

<h2>C. Large aggregate arguments</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>n32 and n64</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>big</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>An aggregate argument is passed to a function;</li>
	  <li>the aggregate's size is not a multiple of 8 bytes; and</li>
	  <li>there are enough argument registers to hold some of
	      the aggregate, but not enough to hold all of it.</li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The argument was passed by reference.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The argument is passed by value.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { int i[17]; };
void f (struct s x);</pre>

	<p>It would take 9 registers to hold <code>x</code>, but
	   only 8 argument registers are available.  Since <code>x</code>'s
	   size is not a multiple of 8, previous releases passed it by
	   reference (that is, they passed a pointer to <code>x</code>
	   in <code>$4</code>).</p>

	<p>The new behavior is to pass <code>x</code> by value.
	   The first 8 words are passed in argument registers and
	   the last is passed on the stack.</p></td>
  </tr>
</table>

<h2>D. Single-field structure arguments</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>o32, o64, n32 and n64</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>either</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>A structure containing a single field is passed by value;
	      and</li>
	  <li>that field has a floating-point type.</li>
        </ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The structure was treated like a scalar value of the same
	floating-point type.  For example, a structure containing a
	<code>float</code> field was treated in the same way as a
	scalar <code>float</code> value.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>There is no special treatment for such structures.
	Note however that the usual n32 and n64 rules still hold:
	naturally-aligned fields of type <code>double</code> are
	passed in floating-point registers.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>struct s { float f; };
void f (struct s x);</pre>

	<p>GCC used to pass <code>x</code> in <code>$f12</code>.
	Now it passes it in <code>$4</code>, just like any other
	structure.</p></td>
  </tr>
</table>

<h2 id="E">E. Structure return values</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>n32 and n64</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>big</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td><ul>
	  <li>An aggregate is returned by value;</li>
	  <li>that aggregate is smaller than 16 bytes;</li>
	  <li>its size is not a multiple of 8 bytes; and</li>
	  <li>if it is a structure, either:
	      <ol>
		<li>it has more than two fields; or</li>
		<li>it has at least one non-floating-point field.</li>
	      </ol></li>
	</ul></td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The return register was padded at the most significant end.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The return register is padded at the least significant end.</td>
  </tr>

  <tr> 
    <th class="right">Example</th>
    <td><pre>struct s { char c[3]; };
struct s f ();</pre>

	<p>f() returns its value in <code>$2</code>, which is laid
	   out as follows:</p>

	<table class="padding5">
	  <tr class="center">
	  <th></th>
	  <th>63-56</th> <th>55-48</th> <th>47-40</th> <th>39-32</th>
	  <th>31-24</th> <th>23-16</th> <th>15-8</th> <th>7-0</th>
	  </tr>

	  <tr class="center">
	  <th class="left">Old&nbsp;behavior</th>
	  <td>padding</td> <td>padding</td> <td>padding</td> <td>padding</td>
	  <td>padding</td> <td>c[0]</td> <td>c[1]</td> <td>c[2]</td>
	  </tr>

	  <tr class="center">
	  <th class="left">New&nbsp;behavior</th>
	  <td>c[0]</td> <td>c[1]</td> <td>c[2]</td> <td>padding</td>
	  <td>padding</td> <td>padding</td> <td>padding</td> <td>padding</td>
	  </tr>
	</table></td>
  </tr>
</table>

<h2>F. Complex return values</h2>

<table class="padding5">
  <tr>
    <th class="right">Affected&nbsp;ABIs</th>
    <td>n32 and n64</td>
  </tr>

  <tr>
    <th class="right">Endianness</th>
    <td>either</td>
  </tr>

  <tr>
    <th class="right">Conditions</th>
    <td>A function returns a complex <code>float</code> or
	<code>double</code>.</td>
  </tr>

  <tr>
    <th class="right">Old&nbsp;behavior</th>
    <td>The value was returned in <code>$f0</code> and <code>$f1</code>.</td>
  </tr>

  <tr>
    <th class="right">New&nbsp;behavior</th>
    <td>The value is returned in <code>$f0</code> and <code>$f2</code>.</td>
  </tr>

  <tr>
    <th class="right">Example</th>
    <td><pre>_Complex float f ();</pre></td>
  </tr>
</table>

</body>
</html>
